#!/usr/sbin/rsct/perl5/bin/perl
# IBM_PROLOG_BEGIN_TAG 
# This is an automatically generated prolog. 
#  
#  
#  
# Licensed Materials - Property of IBM 
#  
# (C) COPYRIGHT International Business Machines Corp. 2000,2004 
# All Rights Reserved 
#  
# US Government Users Restricted Rights - Use, duplication or 
# disclosure restricted by GSA ADP Schedule Contract with IBM Corp. 
#  
# IBM_PROLOG_END_TAG 
#"@(#)06   1.39   src/rsct/rmc/cli/bin/runact.perl, rmccli, rsct_rzauh, rzauh0431a 4/8/04 15:24:19"
######################################################################
#                                                                    #
# Module: runact                                                     #
#                                                                    #
# Purpose:                                                           #
#   runact - Run / invokes an action on a resource or resource class.#
#                                                                    #
# Syntax:                                                            #
#   runact [-h] -s "Selection_string" [-f Resource_data_file]        #
#          [-l|-t|-d|-D Delimiter] [-x] [-T] [-V] Resource_class     #
#          Action [In_Element_0=value In_Element_1=value ...]        #
#          [Rsp_Element...]                                          #
#                                                                    #
#   runact [-h] -r [-f Resource_data_file]                           #
#          [-l|-t|-d|-D Delimiter] [-x] [-T] [-V] Resource_handle    #
#          Action [In_Element_0_value In_Element_1_value ...]        #
#          [Rsp_Element...]                                          #
#                                                                    #
#   runact [-h] -c [-f Resource_data_file] [-n Node_name]            #
#          [-l|-t|-d|-D Delimiter] [-x] [-T] [-V] Resource_class     #
#          Action [In_Element_0=value In_Element_1=value ...]        #
#          [Rsp_Element...]                                          #
#                                                                    #
#   runact [-h] -C Peer_domain_names [-f Resource_data_file]         #
#          [-l|-t|-d|-D Delimiter] [-x] [-T] [-V] Resource_class     #
#          Action [In_Element_0=value In_Element_1=value ...]        #
#          [Rsp_Element...]                                          #
#                                                                    #
# Flags:                                                             #
#   -h      Help. Writes this command's usage statement to stdout.   #
#   -c      Class. Invoke the action on the resource class instead   #
#           of on the resource. By default the action is invoked on  #
#           the resource.                                            #
#   -C Peer_domain_names  Class. Invoke the action on the resource   #
#           class instead of on the resource. The class must be a    #
#           globalized class of a peer domain that exists in a       #
#           management domain.  Peer_domain_names is a list of one   #
#           or more peer domains on which to run the class action.   #
#   -n Node_name  The name of the node on which to run the class     #
#           action.  The -n flag is only allowed with the -c flag.   #
#   -f Resource_data_input_file File input. Specifies the name of    #
#           the file which contains resource or resource class       #
#           input elements. For example:                             #
#           ResourceAction::                                         #
#                  element1 = value                                  #
#                  element2 = value                                  #
#                  ...                                               #
#           - or -                                                   #
#           ResourceClassAction::                                    #
#                  element1 = value                                  #
#                  element2 = value                                  #
#                  ...                                               #
#           Use the lsactdef command with the -i flag to generate a  #
#           template for this input file.                            #
#   -s "Selection string" Specifies the selection string. All        #
#           selection strings must be enclosed within either double  #
#           or single quotation marks. If the selection string       #
#           contains double quotation marks, enclose the entire      #
#           selection string in single quotation marks. For example: #
#           -s 'Name == "testing"'                                   #
#           -s 'Name ?= "test"'                                      #
#           Only persistent attributes can be listed in a selection  #
#           string.                                                  #
#   -r      Resource Handle. Invoke the action on the specific       #
#           resource that matches the specified resource handle.     #
#   -l      Long formatted output. Each element is displayed on a    #
#           separate line. This is the default display format.       #
#   -t      Tabular formatted output. Each element is displayed      #
#           in a separate column, one response per line.             #
#   -d      Delimiter-formatted output. The default delimiter is     #
#           a colon (:). Use the -D flag if you wish to change       #
#           the default delimiter.                                   #
#   -D Delimiter Delimiter formatted output using the specified      #
#           delimiter. Use this flag to specify something other than #
#           the default colon (:). An example is when the data to be #
#           displayed contains colons. Use this flag to specify a    #
#           delimiter of one or more characters.                     #
#   -x      Exclude header. Suppress header printing.                #
#   -T      Trace. Writes the command's trace messages to standard   #
#           error. For your software-service organization use only.  #
#   -V      Verbose. Writes this command's verbose messages to       #
#           standard output.                                         #
#                                                                    #
# Operands:                                                          #
#   Resource_class  The name of the resource class that we want to   #
#                   invoke the action against.                       #
#                                                                    #
#   Action          The name of the action that we want to invoke.   #
#                                                                    #
#   In_Element=value Enter all of the Action input elements and      #
#                   values. If the -f flag is specified, In_Element= #
#                   value pair operands should not be entered on the #
#                   command line. There should be one In_Element=    #
#                   value pair for each of the defined SD input      #
#                   elements for the specified action.               #
#                   Run lsactdef -i Resource Action to generate a    #
#                   template of the required SD input elements for   #
#                   this action.                                     #
#                                                                    #
#   In_Element      Action input element name.                       #
#                   Run lsactdef -si Resource Action to see the      #
#                   action input element names for this Action.      #
#                                                                    #
#   value           The value for this action input element, the     #
#                   value data type must match the definition of     #
#                   this elements data type.                         #
#                   Run lsactdef -si Resource Action to determine    #
#                   the data type.                                   #
#                                                                    #
#   Response_Element Zero or more of the action response element     #
#                   names may be specified. If zero element names    #
#                   are specified, all the elements are displayed.   #
#                   If one or more element names are specified, only #
#                   those elements and their values are displayed    #
#                   in the specified order.                          #
#                                                                    #
# Description:                                                       #
#   The runact command requests the RMC subsystem to run (invoke)    #
#   the specified action on the resource or resource class.          #
#                                                                    #
#   Prior to running runact you should run the lsactdef command      #
#   to determine the action name and action input structured data    #
#   elements that must be specified when invoking an action.         #
#                                                                    #
# Exit Values:                                                       #
#   0  MC_CLI_SUCCESS        Command completed successfully.         #
#   1  MC_CLI_RMC_ERROR      Command terminated due to an underlying #
#                            RMC error.                              #
#   2  MC_CLI_ERROR          Command terminated due to an underlying #
#                            error in the command script.            #
#   3  MC_CLI_BAD_FLAG       Command terminated due to user          #
#                            specifying an invalid flag.             #
#   4  MC_CLI_BAD_OPERAND    Command terminated due to user          #
#                            specifying a bad operand.               #
#   5  MC_CLI_USER_ERROR     Command terminated due to a user error. #
#                            For example specifying an undefined     #
#                            Resource name as the Resource operand.  #
#   6  MC_CLI_NO_RSRC_FOUND  No resources were found that matched    #
#                            the specified selection string.         #
#                                                                    #
# Examples:                                                          #
#   runact -s 'Name == "c175n05"' IBM.Foo TestResourceAction Int32=99#
#   runact -f IBM.Foo.runact1 -s 'Name == "c175n05"'                 #
#      IBM.Foo TestResourceAction                                    #
#      Note: IBM.Foo.runact1 input file would contain the 2 lines:   #
#          ResourceAction::                                          #
#               Int32 = 99                                           #
#   runact -s 'Name ?= "*"' IBM.Foo ExecuteCommand                   #
#      Command=hostname User=root ExitCode Stdout                    #
#                                                                    #
# Man Page:                                                          #
#   For the most current detailed description of this command see    #
#   the runact man page in /usr/sbin/rsct/man.                       #
#                                                                    #
#--------------------------------------------------------------------#
# Inputs:                                                            #
#   /usr/sbin/rsct/msgmaps/mccli.runact.map - message mapping        #
#   /usr/sbin/rsct/msgmaps/mccli.mccil.map - message mapping         #
#                                                                    #
# Outputs:                                                           #
#   stdout - display of Action output response.                      #
#   stderr - any error message.                                      #
#                                                                    #
# External Ref:                                                      #
#   Commands: ctdspmsg                                               #
#   Modules:  MC_cli_utils.pm, MC_cli_display_utils.pm, MC_cli_rc.pm #
#             CT_cli_utils.pm, CT_cli_data_type_utils,               #
#             CT_cli_input_utils.pm, CT_cli_display_utils.pm.        #
#   Extensions:  CT::MC, CT::MCerr, CT::CT, CT::CU                   #
#   Perl library routines: Getopt::Std                               #
#                                                                    #
# Tab Settings:                                                      #
#   4 and tabs should be expanded to spaces before saving this file. #
#   in vi:  (:set ts=4  and   :%!expand -4)                          #
#                                                                    #
# Change Activity:                                                   #
#   000517 SAB 64351: Initial design & write.                        #
#   001120 GTM 67900: Add response element, resource handle support. #
#   010311 SAB 63852: Prepared for GA.                               #
#   010406 SAB 71892: Support new MC_CLI_NO_RSRC_FOUND return code.  #
#   011216 JAC 77349: Add -n flag, node_name for class action (1).   #
#   011217 JAC 79061: Remove using a default for nodenamelist.       #
#   020925 JAC 87393: Change CT_cli_display_utils to .._displayext.. #
#   030123 JAC 91151: Fixes for extensionless version.               #
#   030205 JAC 91360: Escape inner quotes in select strings.         #
#   030318 JAC 92966: Fix for no args and bad action name.           #
#   030402 JAC 93181: Fix for some arg types not passed correctly.   #
#   030404 JAC 92787: Don't allow -s "" for selection string.        #
#   030709 JAC 96745: Add delimiter to call to remove_api_error.     #
#   040111 JAC 100165: Add -C flag for peer domains in DM scope.     #
#   040116 JAC 103144: Fix for typo introduced by 100165.            #
#   040407 JAC 105863: Use escape_chars for "\" searches.            #
######################################################################

#--------------------------------------------------------------------#
# General Program Flow/Logic:                                        #
#                                                                    #
# A. Parse command line flags and operands, determine which flavor   #
#    of this command we are actually invoking.                       #
#       * Invoke a resource class action.                            #
#       * Invoke a resource action.                                  #
# B. Initialize a session with RMC.                                  #
# C. If a resource handle was specified we need to determine which   #
#    resource class it belongs to. So we can get the data types.     #
# D. If a selection string and resource class were specified we need #
#    to get the resource handles associated with the resources that  #
#    match the selection string for the specified class.             #
# E. Query the definition of the action input.                       #
# F. Query the definition of the action response (output).           #
# G. Parse the element = value pairs from the command line or        #
#    from the input file.                                            #
# H. Invoke the action on each of the resource handles.              #
# E. Display the Action response.                                    #
# F. Cleanup.                                                        #
#--------------------------------------------------------------------#

#--------------------------------------------------------------------#
# Included Libraries and Extensions                                  #
#--------------------------------------------------------------------#
use lib "/usr/sbin/rsct/pm";
use locale;
use Getopt::Std; 

use autouse CT_cli_utils => qw(
    printIMsg
    printEMsg
);
use autouse CT_cli_input_utils => qw(
    process_input_file
    process_cmdline_input
    string_to_rsrc_handle
    escape_chars
);

use MC_cli_rc qw(:return_codes); 
use autouse MC_cli_utils => qw(
    error_exit
    build_HoAttr
    printCEMsg
    get_class_from_rsrc_hndl_api
    convert_input_value_api
    process_api_error
    process_exit_code
    remove_api_error
);
use autouse MC_cli_display_utils => qw(
    display_resource_data_api2
);


#--------------------------------------------------------------------#
# Global Variables                                                   #
#--------------------------------------------------------------------#
$TRUE = 1;
$FALSE = 0;

$Verbose = $FALSE;                      # default - verbose turned off

# By default output, attribute name value pairs should be entered
# via the command line.  Attr=value   e.g. Name=c175n06 NodeNumber=1
$Opt_RSRC_Class = $FALSE;               # default - see -c (class)
$Opt_RSRC_Class_DM = $FALSE;            # default - see -C (class)
$Opt_Class = $FALSE;                    # either -C or -c 
$Opt_File_Input = $FALSE;               # default - see -f (file form)
$Opt_RSRC_Handle = $FALSE;              # default - see -r (rsrc hndl)
$Opt_Select_Str = $FALSE;               # default - see -s (selectstr)
$Opt_Long_Format = $TRUE;               # default - see -l (long form)
$Opt_Table_Format = $FALSE;             # default - see -t (tabular)
$Opt_Delm_Format = $FALSE;              # default - see -d (delimiter)
$Opt_Delm_Str = ":";                    # default - see -D (colon :)
$Opt_No_HDR = $FALSE;                   # default - see -x

$PROGNAME = "runact";                   # Program Name for messages
$MSGCAT = "mccli.cat";                  # msg catalogue for this cmd

$CTDIR = "/usr/sbin/rsct";              # RSCT root directory 
$CTBINDIR = "$CTDIR/bin";               # Cluster Bin directory path
$LSMSG = "$CTBINDIR/ctdspmsg";          # list / display message rtn.
$ENV{'MSGMAPPATH'} = "$CTDIR/msgmaps";  # msg maps used by $LSMSG 

#--------------------------------------------------------------------#
# Variables                                                          #
#--------------------------------------------------------------------#
my %HoSDInDef = ();                     # Action input SD Definition
my %HoSDRspDef = ();                    # Action response SD Def
my %HoClassNames = ();
my @LoSDIn = ();                        # Action input SD
my @resource_handles = ();
my $rsp_elements;                       # Reference to array of 
                                        # response element names. 
my $in_elements;                        # Reference to array of 
                                        # In_Element=value pairs
my $rc = 0, $badrc = 0;
my $rsrc_class_id = 0;
my $rHoSD;

my $node_names = "";                    # -n node names
my $peer_domain_names = "";             # -C peer domain names
my @node_name_list = ();                # node names in an array
my $name_count;                         # number of nodes in list 
                                        # (only allow 1 today)
my @lsr_out = ();                       # lsrsrcdef-api output
my @run_out = ();                       # runact-api output
my $cmdstr = "";                        # runact-api parameters
my $cmdstr_tmp = "";                    # runact-api parameters
$DELIMITER = "tvrtvrtvr";               # delimiter for runact-api

#--------------------------------------------------------------------#
# Main Code                                                          #
#--------------------------------------------------------------------#

# set the quote string environment variable, if necessary
if (!defined $ENV{CT_CLI_QUOTE_STRING}){
   $ENV{CT_CLI_QUOTE_STRING} = 1;
}

# parse the command line, exit if there are errors 
($rc, $resource, $r_rsrc_handle, $action, $filename, 
    $select_str, $node_names, $peer_domain_names, $in_elements,
    $rsp_elements) = &parse_cmd_line;
($rc == 0) || error_exit($rc);

# If the -r flag was specified then the user is specifying the
# actual resource handle on the command line and wants the
# resource associated with this resource handle removed.
# Determine which resource class this resource handle is associated.
if ($Opt_RSRC_Handle) {
    $r_rsrc_handle = $resource;
    ($rc, $resource) = get_class_from_rsrc_hndl_api($r_rsrc_handle);
    ($rc == 0) || error_exit($rc);

    push @resource_handles, $r_rsrc_handle;
}

# If the -s flag was specified then a selection string and
# resource class name were provided as input to this command.
# Call the MC_cli_utils::enumerate_resources function, which calls
# RMC function mc_enumerate_resources_bp, to get a list
# of resource handles that match the selection criteria that
# was specified by the user. These resource handles are the 
# ones we need to invoke the action on. This could be an empty list!
#if ($Opt_Select_Str) {               # No resource operand
#    $rc = enumerate_resources($session, $resource, $select_str,
#            \@resource_handles);
#    ($rc == 0) || error_exit($rc); 
#    if (scalar(@resource_handles) == 0) {
#        printCEMsg("EMsgMCcliNoRsrcFound");
#        $rc = MC_CLI_NO_RSRC_FOUND;
#        error_exit($rc);
#    }
#}

# set $Opt_Class if either -c or -C used
if ($Opt_RSRC_Class || $Opt_RSRC_Class_DM) {
   $Opt_Class = $TRUE;
}

# Call lsrsrcdef-api to get the input and response elements
# for the action
if ($Trace) { print STDERR "$PROGNAME: calling lsrsrcdef-api\n";}

# set up flags for resource action
my $flg1 = " -x";
my $flg2 = " -y";
my $flg3 = " -a";

# change the flags if it's a class action
if ($Opt_Class) {
   $flg1 = " -X";
   $flg2 = " -Y";
   $flg3 = " -A";
}

@lsr_out = `$CTBINDIR/lsrsrcdef-api $flg3 ${resource}::${action} $flg1 ${resource}::${action} $flg2 ${resource}::${action} 2>&1`;

# capture the return code from lsrsrcdef-api
$rc = $?;
$rc = process_exit_code($rc);

if ($Trace) { print STDERR "lsrsrcdef-api results:\n";
          print STDERR "@lsr_out";
          print STDERR "$PROGNAME: lsrsrcdef-api returned $rc\n";}

# show any errors if there was a bad rc
if ($rc != 0) {
   process_api_error("::",$rc,@lsr_out);
}

# remove any error messages from the output to display
@lsr_out = remove_api_error("::",@lsr_out);

# exit user error if nothing came back from lsrsrcdef-api
# must be action not found
if ($#lsr_out < 0) {
   printCEMsg("EMsgMCcliUndefinedActionName", $resource);
   exit (MC_CLI_USER_ERROR);
}

# remove the action def from @lsr_out[0]
shift @lsr_out;

# form the input and response SD definitionas from the
# lsrsrcdef-api output
format_sd_element_defs ($resource, \@lsr_out, 
         \%HoSDInDef, \%HoSDRspDef);

# Get the SD element=value pairs to construct the action input SD 
# from either the command line (@$in_elements) or input file.
($rc, $rLoRsrcData) = process_input($Opt_File_Input, $filename, 
    $Opt_Class, $in_elements);
($rc == 0) || error_exit($rc);

# if there are no arguments for this action, build the
# command without them
if ($#$rLoRsrcData <0) {
   $cmdstr = build_action_input_no_sd($resource, $action,
        $r_rsrc_handle, $select_str, $node_names, $peer_domain_names);
}

else {
   # Merge the attr=value pairs you got from the user with the 
   # resources actual attribute definitions to build a Hash of 
   # Persistent Attributes which contains the equivalent data as 
   # the mc_attribute_t structure ({at_name} {at_dtype} {at_value}) 
   # The data you need to actually define the resource - also 
   # check that the user supplied values for all the required 
   # attributes
   foreach $new_action (@$rLoRsrcData) {
       ($rc, $cmdstr_temp) = build_action_input_sd($resource, $action,
           $r_rsrc_handle, $select_str, $node_names, $peer_domain_names,
           $new_action, \%HoSDInDef); 
       if ($rc != 0) {
           if (!$badrc) { $badrc = $rc; }
           next;
       }
       # add it to the final command
       $cmdstr .= " " . $cmdstr_temp;
   }   # end foreach $new_action
}

# call runact-api 
if ($Trace) { 
   print STDERR "$PROGNAME: calling runact-api\n";
   print STDERR "$PROGNAME: calling runact-api with $cmdstr\n";
}

@run_out = `$CTBINDIR/runact-api -D $DELIMITER -I $DELIMITER $cmdstr 2>&1`;

# capture the return code from runact-api
$rc = $?;
$rc = process_exit_code($rc);

if ($Trace) { print STDERR "runact-api results:\n";
          print STDERR "@run_out";
          print STDERR "$PROGNAME: runact-api returned $rc\n";}

# show any errors if there was a bad rc
if ($rc != 0) {
   process_api_error($DELIMITER,$rc,@run_out);
   $badrc = $rc;
}

# remove any error messages from the output to display
@run_out = remove_api_error($DELIMITER,@run_out);

# Display the action's response
$rc = format_and_display_SD(\@run_out, $rsp_elements, 
      \%HoSDRspDef);
($rc == 0) || error_exit($rc);

($badrc == 0) || exit($badrc);

exit $rc;

#--------------------------------------------------------------------#
# End Main Code                                                      #
#--------------------------------------------------------------------#


#--------------------------------------------------------------------#
# parse_cmd_line - Parse the command line for options and operands.  #
#   Set appropriate global variables as outlined below, make sure we #
#   have a valid combination of arguments / options.                 #
#                                                                    #
# Return:                                                            #
#   $rc   0                  Command line parsed fine, no problem.   #
#         SR_CLI_BAD_FLAG    Command line contained a bad flag.      #
#   $resource                Resource Class Name.                    #
#   $r_rsrc_handle           Reference to a resource handle.         #
#   $action                  Action Name.                            #
#   $rsrc_file               Name of file that contains rsrc data    #
#   $select_str              Selection string.                       #
#   $node_names              node name for class action              #
#   @in_elements             Reference to an array of                #
#                            Input element = value pairs.            #
#   @out_elements            Reference to an array of the            #
#                            Output element names to be displayed.   #
#                                                                    #
# Global Variables Modified:                                         #
#   $Opt_RSRC_Class    output   True (-c), invoke action on resource #
#                               class.                               #
#   $Opt_RSRC_Class_DM output   True (-C), invoke action on resource #
#                               class on peer domains in DM scope.   #
#   $Opt_Select_Str    output   True (-s select_string), invoke      #
#                               action on resources that match       #
#                               specified selection string.          #
#   $Opt_RSRC_Handle   output   True (-r), invoke action on this     #
#                               resource handle specified as operand.#
#   $Opt_File_Input    output   True (-f) read rsrc data from file.  #
#   $Opt_Long_Format   output   True (-l) print one entry per line   #
#   $Opt_Table_Format  output   True (-t) print in table format.     #
#   $Opt_Delm_Format   output   True (-d|-D) print delimitter        #
#                               separated output.                    #
#   $Opt_Delm_Str      output   the string to use as the delimitter, #
#                               default is colon (:).                #
#   $Opt_No_HDR        output   True (-x) print without header       #
#   $Verbose           output   True (-V) turn Verbose mode on.      #
#   $Trace             output   True (-T) turn Trace mode on.        #
#--------------------------------------------------------------------#
sub parse_cmd_line 
{
my(@original_argv) = @ARGV;
my $resource = "";
my $action = "";
my $rsrc_file = ""; 
my $select_str = "";
my @in_elements = ();
my @out_elements = ();
my $node_names = "";
my $peer_domain_names = "";
my %opts = ();

# Process the command line...
if (!&getopts('hcC:n:f:rs:dD:ltxVT', \%opts)) { # Get flags, if errors
    &print_usage;                       # display proper usage
    return MC_CLI_BAD_FLAG;             # return bad rc - bad flag 
}

# Always accept the -h help flag regardless of other flags or operands
if (defined $opts{h}) {                 # -h, help request
    &print_usage;                       # print usage statement
    exit(0);                            # all done with good return!
}

# An operand is required.
#   When -s flag specified require operand to be a resource class name
#   When -r flag specified require operand to be a resource handle
if ($#ARGV >= 0) {
    # Get the arguments...
    # Operands:  [resource | resource_handle]
    $resource = shift @ARGV;            # user specified resources
    if ($#ARGV >= 0) {
        $action = shift @ARGV;          # user specified action
    }
    else {
        printCEMsg("EMsgMCcliMissingAction");
        &print_usage;
        return MC_CLI_BAD_OPERAND;          # return bad rc - bad operand
    }
}
else {
    (defined $opts{s}) && printCEMsg("EMsgMCcliMissingRsrcClass");
    (defined $opts{r}) && printCEMsg("EMsgMCcliMissingRsrcHandle");
    &print_usage;
    return MC_CLI_BAD_OPERAND;          # return bad rc - bad operand
}

                                        # need to handle sd input and
# Grab all of the In_Element=value pairs that must come before the
# Out_Element operands. The regular expression sees if the next 
# argument / operand is of the form keyword=value. 
if ($#ARGV >= 0) {                      
    my $num_elements = $#ARGV + 1; 
    for (my $i= 0; $i < $num_elements; $i++) {
        if ($ARGV[0] =~ /(\w+)\s*=\s*(.*?)\s*/) { # arg keyword=value
            push @in_elements, shift @ARGV;
        }
        else {  
            last; 
        }
    }
}           

# The remaining arguments / operands are the Out_Elements
# The Action output response element names that should be displayed
if ($#ARGV >= 0) {
    @out_elements = @ARGV;
}

# See which options/flags were used...

if (defined $opts{c}) {                 # -c, invoke act on rsrc class
    $Opt_RSRC_Class = $TRUE;
    if (defined $opts{s}) {
        printCEMsg("EMsgMCcliImproperUsageCombination", "-c", "-s");
        &print_usage;
        return MC_CLI_BAD_FLAG;
    }

    # check for -n node_names option
    if (defined $opts{n}) {
        $node_names = $opts{n};
    }
}

if (defined $opts{C}) {                 # -C, invoke act on rsrc class
    $Opt_RSRC_Class_DM = $TRUE;
    $peer_domain_names = $opts{C};
    if (defined $opts{s}) {
        printCEMsg("EMsgMCcliImproperUsageCombination", "-C", "-s");
        &print_usage;
        return MC_CLI_BAD_FLAG;
    }
    if (defined $opts{c}) {
        printCEMsg("EMsgMCcliImproperUsageCombination", "-C", "-c");
        &print_usage;
        return MC_CLI_BAD_FLAG;
    }
    if (defined $opts{n}) {
        printCEMsg("EMsgMCcliImproperUsageCombination", "-C", "-n");
        &print_usage;
        return MC_CLI_BAD_FLAG;
    }
}

if (defined $opts{f}) {                 # -f, filename for rsrc data
    $Opt_File_Input = $TRUE;
    $rsrc_file = $opts{f};              # input rsrc file name
    if (scalar @in_elements > 0) {
        # Can't use -f with In_element on cmd line
        printCEMsg("EMsgMCcliImproperUsageCombination", "-f", 
            @in_elements);
        &print_usage;
        return MC_CLI_BAD_OPERAND;
    }       
}

if (defined $opts{r}) {                 # -r, rm using rsrc handles
    $Opt_RSRC_Handle = $TRUE;
    ($rc, $r_rsrc_handle) = string_to_rsrc_handle($resource);
    if ($rc != 0) {
        printCEMsg("EMsgMCcliBadRsrcHandle", $resource); 
        &print_usage;
        return MC_CLI_BAD_OPERAND; 
    }
    if (defined $opts{c}) {
        printCEMsg("EMsgMCcliImproperUsageCombination", "-c", "-r");
        &print_usage;
        return MC_CLI_BAD_FLAG;
    }
    if (defined $opts{n}) {
        printCEMsg("EMsgMCcliImproperUsageCombination", "-n", "-r");
        &print_usage;
        return MC_CLI_BAD_FLAG;
    }
    if (defined $opts{s}) {
        printCEMsg("EMsgMCcliImproperUsageCombination", "-s", "-r");
        &print_usage;
        return MC_CLI_BAD_FLAG;
    }
    if (defined $opts{C}) {
        printCEMsg("EMsgMCcliImproperUsageCombination", "-C", "-r");
        &print_usage;
        return MC_CLI_BAD_FLAG;
    }
}

if (defined $opts{s}) {                 # -s "selection_string"
    $select_str = $opts{s};
    # don't allow empty selection string 
    if ($select_str =~ /^$/) {
        printCEMsg("EMsgMCcliSelectStrError");
        &print_usage;
        return MC_CLI_BAD_OPERAND;
    }
    $Opt_Select_Str = $TRUE;
}
elsif (!defined $opts{c} && !defined $opts{r} && !defined $opts{C}) {
    printCEMsg("EMsgMCcliMissingSelectionStr");
    &print_usage;
    return MC_CLI_BAD_FLAG;
}

# The -l overrides the -t which overrides the -d which overrides -D
# Long is the default display format 
if (defined $opts{l}) {
    $Opt_Long_Format = $TRUE;
}
elsif (defined $opts{t}) {
    $Opt_Table_Format = $TRUE;          # -t tabular format
    $Opt_Long_Format = $FALSE;
}
elsif (defined $opts{d}) {              # -d delimitter format
    $Opt_Delm_Format = $TRUE;
    $Opt_Long_Format = $FALSE;
}
elsif (defined $opts{D}) {              # -D <delimitter> format
    $Opt_Delm_Format = $TRUE;
    $Opt_Long_Format = $FALSE; 
    $Opt_Delm_Str = $opts{D};
}

if (defined $opts{x}) {                 # -x do not print header
    $Opt_No_HDR = $TRUE;
}

if (defined $opts{T}) {                 # -T, turn tracing on 
    $Trace = $TRUE; 
}

if (defined $opts{V}) {                 # -V, turn verbose mode on 
    $Verbose = $TRUE;
}

# success
return(0, $resource, $r_rsrc_handle, $action, $rsrc_file, 
    $select_str, $node_names, $peer_domain_names, \@in_elements, \@out_elements);
}   # end parse_cmd_line


#--------------------------------------------------------------------#
# print_usage : print the usage statement (syntax) to stdout.        #
#   See this command's prologue syntax section for current usage.    #
#--------------------------------------------------------------------#
sub print_usage
{
printIMsg("IMsgrunactUsage3");
}   # end print_usage



#--------------------------------------------------------------------#
# format_sd_element_defs - formats the structured data elements into #
#   a complex hash of SD element definitions (%rHoSDEleDefs).        #
#   The level 1 hash                                                 #
#     key = element_name data = hash                                 #
#     or                                                             #
#     key = element_index data = hash                                #
#   Typically when processing the SD input def we want the key       #
#   to be the element_name.  But when processing the SD response def #
#   where we want to display the response SD, having the key as      #
#   the SD element index makes more sense.                           #
#   The level 2 hash                                                 #
#     key = (sd_name, sd_dtype, sd_index, sd_value)                  #
#     the values from mc_qdef_sd_bp of those fields                  #
#   Example:                                                         #
#     x $rHoSDEleDefs                                                #
#     0  'Int32'                                                     #
#     1  HASH(0x2045ddd0)                                            #
#        'sd_dtype' => 2                                             #
#        'sd_index' => 0                                             #
#        'sd_name' => 'Int32'                                        #
#        'sd_value' => undefined                                     #
#     or                                                             #
#     0  0                                                           #
#     1  HASH(0x2045ddd0)                                            #
#        'sd_dtype' => 2                                             #
#        'sd_index' => 0                                             #
#        'sd_name' => 'Int32'                                        #
#        'sd_value' => undefined                                     #
#                                                                    #
# Parameters:                                                        #
#   $resource         input   Resource Name                          #
#   $response         input   Reference to array returned by         #
#                             lsrsrcdef-api.                         #
#   %$rHoSDEleDefs    in/out  Reference to the hash of SD element    #
#                             definitions.                           #
#   $hash_by_name     input   TRUE - hash by element_name.           #
#                             FALSE - hash by element_index.         #
#                                                                    #
# Global References:                                                 #
#   None.                                                            #
#--------------------------------------------------------------------#
sub format_sd_element_defs
{
#my($resource, $response, $rHoSDEleDefs, $hash_by_name) = @_;
my($resource, $response, $rHoSDEleDefsIn, $rHoSDEleDefsResp) = @_;

my %elements = ();
my @resp_info = ();
my ($element_name, $element_index, $element_cnt);

# get count of array elements
my $response_cnt = $#$response;

# keep track of if we're processing input or response
my $Input = $TRUE;

# form the hash
for (my $e = 0; $e <= $response_cnt; $e++) {
    %elements = ();
    chomp($$response[$e]);
    @resp_info = split (/::/, $$response[$e]);
    $element_name = $resp_info[1];
    $element_name =~ s/\"//g;
    $element_index = $resp_info[5];
    $elements{sd_name} =  $element_name;
    $elements{sd_index} = $element_index;
    $elements{sd_dtype} = $resp_info[2];
#   if ($hash_by_name) {
#       $$rHoSDEleDefs{$element_name} = { %elements };
#   }
#   else {
#       $$rHoSDEleDefs{$element_index} = { %elements };
#   }

    # assign to proper structure
    if ($Input) {
        $$rHoSDEleDefsIn{$element_name} = { %elements };
    }
    else {
        $$rHoSDEleDefsResp{$element_name} = { %elements };
    }

    # see if input has ended and responses are next
    if ( ($e < $response_cnt) && ($$response[$e+1] =~ /::0\n$/) ) {
        $Input = $FALSE;
    } 
}   # end for each response

return;
}   # end of format_sd_element_defs

#--------------------------------------------------------------------#
# process_input - process the attr=value pairs that are used to      #
#   define this resource and were input by the user on the command   #
#   line or via an input file.                                       #
#                                                                    #
# Parameters:                                                        #
#   $Opt_File_Input   input   True - input should come from file.    #
#                             False - input should come from command #
#                             line.                                  #
#   $filename         input   Name of file if $Opt_File_Input = TRUE #
#   $Opt_Class        input   True if invoking action on a resource  #
#                             class instead of a resource.           #
#   @$r_cmdline       input   Reference to attr=value pairs via      #
#                             command line and ARGV.                 #
#                                                                    #
# Return:                                                            #
#   $rc                       return code.                           #
#                                                                    #
# Global References:                                                 #
#   None.                                                            #
#--------------------------------------------------------------------#
sub process_input 
{
my ($Opt_File_Input, $filename, $Opt_Class, $r_cmdline) = @_;
my $rc = 0;
my $rLoRsrcData;

if ($Opt_File_Input) {
    my $file_stanza; 
    if ($Opt_Class) {
        $file_stanza = "ResourceClassAction";
    }
    else {
        $file_stanza = "ResourceAction";
    }

    ($rc, $rLoRsrcData) = process_input_file($filename, $file_stanza);
    if ($rc != 0) {
        # Print Error processing input file msg
        # process_input_file will write a more detailed error message
        printEMsg("EMsgrunactInputFileError", $filename);
        exit(MC_CLI_USER_ERROR);
    }
}
else {
    # set empyt list if no args
    if ($#$r_cmdline < 0) {
       $rLoRsrcData = $r_cmdline;
    }
    # process the args
    else {
       ($rc, $rLoRsrcData) = process_cmdline_input($r_cmdline);
       if ($rc != 0) {
            # Print Command Line Error Attr=value error msg
            printEMsg("EMsgrunactCmdLineError", $r_cmdline);
            exit(MC_CLI_BAD_OPERAND);
       }
    }
}

if ($Verbose) {
    my ($attribute, $value, $entry, $row_header);
    foreach $entry (@$rLoRsrcData) {
        $row_header = $entry->[0];
        foreach $element (@{$entry->[1]}) {
            $attribute = $element->[0];
            $value = $element->[1];
            print "$attribute = \"$value\"\n";
        }
    }
}
return ($rc, $rLoRsrcData);
}   # end process_input


#--------------------------------------------------------------------#
# build_action_input_sd - function to build up the parameters for    #
#   the runact-api command.                                          #
#                                                                    #
# Parameters:                                                        #
#   $resource         input   Resource name.                         #
#   $action           input   Action name.                           #
#   $handle           input   Resource handle.                       #
#   $selstr           input   Select string.                         #
#   $node_name        input   Node name.                             #
#   $peer_domain_names input  Peer domain names.                     #
#   $rActionData      input   Reference to array of attr,value pairs.#
#   $rHoSDInDef       input   Reference to hash of the action input  #
#                             SD element definitions for this action.#
#                                                                    #
# Return:                                                            #
#   $rc                       return code.                           #
#   $runcmd                   String containing runact-api parms.    #
#                                                                    #
# Global References:                                                 #
#   Opt_RSRC_Class    input   Class action (-c).                     #
#   Opt_RSRC_Class_DM input   Class action (-C).                     #
#   Opt_RSRC_Handle   input   Resource handle specified (-r).        #
#   Opt_Select_Str    input   Select string specified (-s).          #
#   DELIMITER         input   Input delimiter.                       #
#--------------------------------------------------------------------#
sub build_action_input_sd
{
my ($resource, $action, $handle, $selstr, $node_name, $peer_domain_names,
               $rActionData, $rHoSDInDef) = @_; 

my ($new_element, $data_type);
my $element_list = "";         
my ($element_name, $element_value);
my $badrc = 0;
my $runcmd = "";
my $delim = "";

foreach $new_element (@{$rActionData->[1]}) {
    $element_name = $new_element->[0];

    # first check to make sure this is a valid sd element name
    if (!defined($$rHoSDInDef{$element_name})) {
        printEMsg("EMsgrunactInvalidSDElement", $element_name, 
            $resource, $action, '"' . $rActionData->[0] . '"');
        $badrc = MC_CLI_USER_ERROR;
        next;                   # continue validating rest of input
    }   
    
    # Get the elements value 
    $data_type = $rHoSDInDef->{$element_name}{sd_dtype};
    # An SD cannot contain an SD
    if (($data_type =~ /^CT_SD_PTR$/) || ($data_type =~ /^CT_SD_PTR_ARRAY$/)) {
#       my $dtype_str = data_type_to_string($data_type);
        printEMsg("EMsgrunactInvalidDataType", $action, $element_name,
#           $dtype_str);
            $data_type);
        $rc = MC_CLI_USER_ERROR;
    }
#   ($rc, $element_value) = convert_input_value_api($data_type, 
#       $new_element->[1]);
    $element_value = $new_element->[1];

#   # get rid of quotes if resource handle
#   if ($data_type =~ /^CT_RSRC_HANDLE/) {
#       $element_value =~ s/\"//g;
#   }

    # get rid of quotes in arrays, but not in string arrays
    if ( ($data_type =~ /ARRAY$/) && ($data_type !~ /^CT_CHAR_PTR_ARRAY$/) ) {
         $element_value =~ s/\"//g;
    }

#   if ($rc != 0) {      
#       printCEMsg("EMsgMCcliBadEleValue", $element_name,
#            $new_element->[1]);
#       if ($badrc == 0) {$badrc = $rc; }
#       next;
#   }   
#   $rHoSDInDef->{$element_name}{sd_value} = $element_value;
    $element_list .= $delim . $element_name . $DELIMITER . $element_value;
    $delim = $DELIMITER;
}

# put the command together
# for class, it's -c class::node::
if ($Opt_RSRC_Class)  { 
   $runcmd = "-c \"${resource}${DELIMITER}${node_name}"; 
}

# for class, it's -C class::peer_domain_names::
if ($Opt_RSRC_Class_DM)  { 
   $runcmd = "-C \"${resource}${DELIMITER}${peer_domain_names}"; 
   # set DM scope for -C
   $ENV{CT_MANAGEMENT_SCOPE} = 3;
}

# for resource handle, it's -r handle::
elsif ($Opt_RSRC_Handle) { 
   $runcmd = "-r \"$handle"; 
}

# for select string, it's -s class::select_str
elsif ($Opt_Select_Str)  { 

   # escape inner quotes
   #$selstr =~ s/\\/\\\\/g;
   #$selstr =~ s/\"/\\\"/g;
   $selstr = escape_chars($selstr);

   $runcmd = "-s \"${resource}${DELIMITER}${selstr}"; 
}

# escape inner quotes
#$element_list =~ s/\\/\\\\/g;
#$element_list =~ s/\"/\\\"/g;
$element_list = escape_chars($element_list);

# add the action and arg/value pairs
$runcmd .= $DELIMITER . $action . $DELIMITER . $element_list . "\"";

# Get the list of all the input element names in element index
# order. No guarantee that we got them from RMC in correct order
# but we have to make sure we give them to RMC in the correct order.
# Also even if RMC gave them in the correct order we stored them
# in a hash and a hash does not guarantee any order.
#my @required_element_names = get_sd_element_names($rHoSDInDef);

# Make sure that all of the required elements are being
# defined.
#foreach $element_name (@required_element_names) {
#    if (!defined($$rHoSDInDef{$element_name}{sd_value})) {
#        printEMsg("EMsgrunactMissingReqElement", $element_name, 
#            $action);
#        $badrc = MC_CLI_USER_ERROR;
#    }
#}

# Create the structured data structure (an array of hashes 
# with the type and value - with one hash representing each 
# element in the SD. Make sure the order is correct.)
#my @LoSD = ();                  # Create the array
#foreach $element_name (@required_element_names) {
#    my %element = ();
#    $element{type} = $$rHoSDInDef{$element_name}{sd_dtype};
#    $element{value} = $$rHoSDInDef{$element_name}{sd_value};
#    push @LoSD, { %element }; 
#}

return($badrc, $runcmd);
}   # end build_action_input_sd


#--------------------------------------------------------------------#
# build_action_input_no_sd - function to build up the parameters for #
#   the runact-api command when no arguments are used.               #
#                                                                    #
# Parameters:                                                        #
#   $resource         input   Resource name.                         #
#   $action           input   Action name.                           #
#   $handle           input   Resource handle.                       #
#   $selstr           input   Select string.                         #
#   $node_name        input   Node name.                             #
#   $peer_domain_names input  Peer domain names.                     #
#                                                                    #
# Return:                                                            #
#   $runcmd                   String containing runact-api parms.    #
#                                                                    #
# Global References:                                                 #
#   Opt_RSRC_Class    input   Class action (-c).                     #
#   Opt_RSRC_Class_DM input   Class action (-C).                     #
#   Opt_RSRC_Handle   input   Resource handle specified (-r).        #
#   Opt_Select_Str    input   Select string specified (-s).          #
#   DELIMITER         input   Input delimiter.                       #
#--------------------------------------------------------------------#
sub build_action_input_no_sd
{
my ($resource, $action, $handle, $selstr, $node_name, $peer_domain_names) = @_;
my $runcmd = "";
my $delim = "";

# put the command together
# for class, it's -c class::node::
if ($Opt_RSRC_Class)  {
   $runcmd = "-c \"${resource}${DELIMITER}${node_name}";
}

# for class, it's -C class::peer_domain_names::
if ($Opt_RSRC_Class_DM)  {
   $runcmd = "-C \"${resource}${DELIMITER}${peer_domain_names}";
   # set DM scope for -C
   $ENV{CT_MANAGEMENT_SCOPE} = 3;
}

# for resource handle, it's -r handle::
elsif ($Opt_RSRC_Handle) {
   $runcmd = "-r \"$handle";
}

# for select string, it's -s class::select_str
elsif ($Opt_Select_Str)  {

   # escape inner quotes
   #$selstr =~ s/\\/\\\\/g;
   #$selstr =~ s/\"/\\\"/g;
   $selstr = escape_chars($selstr);

   $runcmd = "-s \"${resource}${DELIMITER}${selstr}";
}

# add the action and arg/value pairs
$runcmd .= $DELIMITER . $action . "\"";

return($runcmd);
}   # end build_action_input_sd


#--------------------------------------------------------------------#
# format_and_display_SD - formats and displays the action response   #
#   SD elements.                                                     #
#                                                                    #
# Parameters:                                                        #
#   $response         input   Reference to array of runact-api       #
#                             output.                                #
#   $rlo_elements     input   Reference to list of SD element names. #
#                             If empty print all SD elements else    #
#                             print only the ones specified.         #
#   %$rHoSDRspDef     input   Reference to the hash of SD response   #
#                             definition (from get_sd_element_defs)  #
#                             x %$rHoSDRspDef to see format of hash. #
#                                                                    #
# Global References:                                                 #
#   $Opt_Long_Format  input   TRUE if should display one per line.   #
#   $Opt_Table_Format input   TRUE if should display in table form.  #
#   $Opt_Delm_Format  input   TRUE if should display with delimiter. #
#   $Opt_Delm_Str     input   Actual delimiter to display with.      #
#   $Opt_No_HDR       input   TRUE if should not display header.     #
#   $Opt_Class        input   TRUE if -c or -C used.                 #
#--------------------------------------------------------------------#
sub format_and_display_SD
{
my ($response, $rlo_elements, $rHoSDRspDef) = @_;
my @LoElements = ();
my %HoElements = ();
my %elements = ();
my ($element_name, $element_count);

my $title_col;
my @title_row;
my $print_format = "long";        
my $delim = "";

my $rc = 0;

# Determine if displaying in long, delimiter or tabular/column format.
if ($Opt_Long_Format) {
    $print_format = "long";
}
elsif ($Opt_Table_Format) {
    $print_format = "column";
}
elsif ($Opt_Delm_Format) {
    $print_format = "delim";
    $delim = $Opt_Delm_Str;
}

$title_row = "sd_element";

my @r_info = (); 
my $node_name = "";
my $response_count = $#$response;

for (my $r = 0; $r <= $response_count; $r++) {

    # parse each response 
    chomp($$response[$r]);
    @r_info = split (/$DELIMITER/, $$response[$r]);

    # if there is an odd number of array elements, the 
    # first is the node name of where it came from
    my $rem = $#r_info % 2;
    if (!$rem) { $node_name = shift @r_info; }

#   my @loSDs = $response->data($r);
    my $s = 0;              # number of SDs to be displayed
    # format the responses 
    for (my $k = 0; $k <= $#r_info; $k=$k+2) {
         %elements = ();
         $element_name = $r_info[$k];
         $elements{at_name} = $element_name;
         $elements{at_dtype} = ${$rHoSDRspDef}{$element_name}{sd_dtype};
         $elements{at_value} = $r_info[$k+1];

         # quote any resource handles and binary values
         if ( ($elements{at_dtype} =~ /^CT_RSRC_HANDLE_PTR$/) ||
              ($elements{at_dtype} =~ /^CT_BINARY_PTR$/) ) {
            $elements{at_value} = "\"" . $elements{at_value} . "\"";
         }
         if ( ($elements{at_dtype} =~ /^CT_RSRC_HANDLE_PTR_ARRAY$/) ||
              ($elements{at_dtype} =~ /^CT_BINARY_PTR_ARRAY$/) ) {
            $elements{at_value} =~ s/\{/\{\"/;
            $elements{at_value} =~ s/\}/\"\}/;
            $elements{at_value} =~ s/,/\",\"/;
         }

         build_HoAttr($element_name, \@LoElements, \%HoElements,
              \%elements, $s);   
    }
    $s++;     # number of SDs to be displayed
}   # end for each response

# TODO: In future may want to display only one response worth of
# data at a time if lots of data is returned.

# Display the SD elements in the order that they were requested
# on the command line.  If no response element names were specified 
# on the command line display them in the order that RMC returned
# them.

if (scalar(@$rlo_elements) == 0) {
    $rlo_elements = \@LoElements;
}
else {
    # ensure all response elements from cmd line are valid
    foreach $element (@$rlo_elements) {
        if (!exists ${$rHoSDRspDef}{$element}) {
            printEMsg("EMsgrunactBadRspElt", $element, $action);
            $rc = MC_CLI_USER_ERROR;
        }
    }
    ($rc == 0) || return $rc;
}

# Display the header to the output here since it needs
# to use a catalogued message.
$title_col = "";
if (!$Opt_No_HDR) {
    ($Opt_Class) ?
        printIMsg("IMsgrunactRsrcClassRspHdr", $action) :
        printIMsg("IMsgrunactRsrcActRspHdr", $action);
}

# Only display table header first time display everything from
# one response
$rc = display_resource_data_api2($print_format, $Opt_No_HDR, $rlo_elements,
        $title_row, \%HoElements, $delim, $title_col);

return $rc;
}   # end format_and_display_SD


#--------------------------------------------------------------------#
# error_check - checks the return code from the RMC function and     #
#   the error response return code.  If an error is detected         #
#   appropriate error messages will be displayed.                    #
#                                                                    #
# Parameters:                                                        #
#   $rmc_function     in      Name of the rmc function that was      #
#                             called and whose error code we are     #
#                             checking.                              #
#   $rmc_class        in      The resource class name.               #
#   $action           in      The action name.                       #
#   $response         in      RMC response.                          #
#   $rmc_rc           in      The rmc function return code.          #
#   $error            in      The error response.                    #
#                                                                    #
# Return:                                                            #
#   $rc                       return code.                           #
#                                                                    #
# Global References:                                                 #
#   None.                                                            #
#--------------------------------------------------------------------#
sub error_check
{
my ($rmc_function, $rmc_class, $action, $response,
    $rmc_rc, $error) = @_;

my $rc = 0;
my $err_rc = $error->errnum();

if ($rmc_rc != 0) {
    printEMsg("EMsgrunactRunActError", $action);
    my $rmc_rc_hex = sprintf "0x%8.8lx", $rmc_rc;
    printCEMsg("EMsgMCcliMCFunctionFailure", $rmc_function,
        $rmc_rc, $rmc_rc_hex);
    $rc = MC_CLI_RMC_ERROR;
    return $rc;
}

# Check the errnum in each of the RMC responses
for (my $r = 0; $r < $response->array_count; $r++) {
    # get the error that goes with the specific response
    if ($r > 0) {
        $response->error($error, $r);
        $err_rc = $error->errnum();
    }
    if ($err_rc != 0) {
        if ($err_rc == RMC_ECLASSNOTDEFINED) {
            printCEMsg("EMsgMCcliClassNotDef", $rmc_class);
            $rc = MC_CLI_USER_ERROR;
        }
        elsif ($err_rc == RMC_EBADACTIONNAM) {
            print STDERR $error->error_msg;
            $rc = MC_CLI_USER_ERROR;
        }   
        elsif ($err_rc == RMC_EACCESS) {
            print STDERR $error->error_msg;
            $rc = MC_CLI_USER_ERROR;
        }
        elsif ($err_rc >= 0x60000 && $err_rc <= 0x6ffff) {
            # Selection string errors are in this range
            printCEMsg("EMsgMCcliSelectStrError");
            print STDERR $error->error_msg;
            $rc = MC_CLI_USER_ERROR;
        }
        else {
            printEMsg("EMsgrunactRunActError", $action);
            my $err_rc_hex = sprintf "0x%8.8lx", $err_rc;
            printCEMsg("EMsgMCcliMCFunctionFailure", $rmc_function, 
                $err_rc, $err_rc_hex);
            print STDERR $error->error_msg; 
            $rc = MC_CLI_RMC_ERROR;
        }
    }   # end if
}   # end for

return $rc;
}   # end error_check
